#region Copyright
// 
// Copyright (C) 2008 VirtualStaticVoid <virtualstaticvoid@gmail.com>
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
#endregion

using System;

namespace NAom.Core
{
  internal class DynamicTypeFactory<TType> : IDynamicTypeFactory<TType>
    where TType : class
  {

    public DynamicTypeFactory(DynamicType<TType> dynamicType, Type generatedType, ReadOnlyNamedItemCollection<IPropertyType> properties)
    {
      if (dynamicType == null) throw new ArgumentNullException("dynamicType");
      if (generatedType == null) throw new ArgumentNullException("generatedType");
      if (properties == null) throw new ArgumentNullException("properties");
      DynamicType = dynamicType;
      GeneratedType = generatedType;
      Properties = properties;

    }

    public Type GeneratedType { get; private set; }

    public ReadOnlyNamedItemCollection<IPropertyType> Properties { get; private set; }

    IDynamicType IDynamicTypeFactory.DynamicType
    {
      get { return this.DynamicType; }
    }

    object IDynamicTypeFactory.CreateInstance(params object[] args)
    {
      return CreateInstance(args);
    }

    public DynamicType<TType> DynamicType { get; private set; }

    public TType CreateInstance()
    {
      return InternalCreateInstance();
    }

    public TType CreateInstance<TArg1>(TArg1 arg1)
    {
      return InternalCreateInstance(arg1);
    }

    public TType CreateInstance<TArg1, TArg2>(TArg1 arg1, TArg2 arg2)
    {
      return InternalCreateInstance(arg1, arg2);
    }

    public TType CreateInstance<TArg1, TArg2, TArg3>(TArg1 arg1, TArg2 arg2, TArg3 arg3)
    {
      return InternalCreateInstance(arg1, arg2, arg3);
    }

    public TType CreateInstance<TArg1, TArg2, TArg3, TArg4>(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4)
    {
      return InternalCreateInstance(arg1, arg2, arg3, arg4);
    }

    public TType CreateInstance<TArg1, TArg2, TArg3, TArg4, TArg5>(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5)
    {
      return InternalCreateInstance(arg1, arg2, arg3, arg4, arg5);
    }

    public TType CreateInstance<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6>(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6)
    {
      return InternalCreateInstance(arg1, arg2, arg3, arg4, arg5, arg6);
    }

    public TType CreateInstance<TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7>(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5, TArg6 arg6, TArg7 arg7)
    {
      return InternalCreateInstance(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
    }

    public TType CreateInstance(params object[] args)
    {
      return InternalCreateInstance(args);
    }

    private TType InternalCreateInstance(params object[] args)
    {
      // REFACTOR to invoke dynamic method, which calls newobj instead!
      return (TType)Activator.CreateInstance(GeneratedType, args);
    }

  }
}
